﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Specialized;
using System.Collections;
using System.Reflection;
using System.Web.Compilation;

namespace Doo.ServerControls
{
    /// <summary>
    /// 使用DataClass的数据源
    /// </summary>
    [ToolboxData("<{0}:DataClassSource runat=server></{0}:DataClassSource>")]
    public class DataClassSource : DataSourceControl
    {
        const string defaultViewName = "defaultView";

        /// <summary>
        /// 数据类名
        /// </summary>
        public string UpdateClassName
        {
            get { return View.UpdateClassTypeName; }
            set { View.UpdateClassTypeName = value; }
        }

        /// <summary>
        /// 数据类名
        /// </summary>
        public string ListClassName
        {
            get { return View.ListClassTypeName; }
            set { View.ListClassTypeName = value; }
        }

        public bool SelectByRecord { get { return View.SelectByRecord; } set { View.SelectByRecord = value; } }

        protected override DataSourceView GetView(string viewName)
        {
            View.defaultAssembly = Page.GetType().Assembly;
            return View;
        }

        protected Doo.DataClass.DataClassView _view;

        public Doo.DataClass.DataClassView View
        {
            get
            {
                if (_view == null)
                {
                    _view = new Doo.DataClass.DataClassView(this, defaultViewName);
                }
                return _view;
            }
        }

        protected override ICollection GetViewNames()
        {
            return new string[] { defaultViewName };
        }

        public IOrderedDictionary Keys { get { return View.SelectKeys; } set { View.SelectKeys = value; } }
    }

}

namespace Doo.DataClass
{
    public class DataClassView : DataSourceView
    {
        public DataClassView(IDataSource source, string viewName)
            : base(source, viewName)
        {

        }

        public Assembly defaultAssembly;

        public override bool CanUpdate
        {
            get
            {
                return true;
            }
        }

        public override bool CanInsert
        {
            get
            {
                return true;
            }
        }

        public override bool CanDelete
        {
            get
            {
                return true;
            }
        }

        protected bool SaveUpdate(IDictionary keys, IDictionary values, DataClass.UpdateMode mode)
        {
            Type classType = UpdateClassType;
            object classinstance = GetInstance(classType, keys);
            // g
            var entityType = classType.GetProperty("EntityType").GetValue(classinstance, null) as Type;
            // up func
            var mi = typeof(UpdateClassHelper).GetMethod("ConvertToUpdateFunc").MakeGenericMethod(entityType);
            var func = mi.Invoke(null, new object[] { values });
            var pinfo = classType.GetProperty("UpdateFunc");
            pinfo.SetValue(classinstance, func, null);
            //set mode
            if ((int)mode > 0)
            {
                var modep = classType.GetProperty("Mode");
                modep.SetValue(classinstance, mode, null);
            }
            //u
            var method = classType.GetMethod("Process", Type.EmptyTypes);
            bool su = (bool)method.Invoke(classinstance, null);
            if (su && keys.Count > 0)
            {
                //重新设置keys
                OrderedDictionary updatedKeys = new OrderedDictionary();
                foreach (DictionaryEntry keyentry in keys)
                {
                    PropertyInfo keyinfo = classType.GetProperty((string)keyentry.Key);
                    updatedKeys.Add(keyentry.Key, keyinfo.GetValue(classinstance, null));
                }
                this.UpdatedKeys = updatedKeys;
            }
            //获取return record
            var returnrecordinfo = classType.GetProperty("ReturnRecord");
            _returnrecord = returnrecordinfo.GetValue(classinstance, null);
            return su;
        }

        public IOrderedDictionary UpdatedKeys { get; set; }

        private object _returnrecord;
        public object ReturnRecord { get { return _returnrecord; } }

        public override void Update(System.Collections.IDictionary keys, System.Collections.IDictionary values, System.Collections.IDictionary oldValues, DataSourceViewOperationCallback callback)
        {
            this.SaveUpdate(keys, values, UpdateMode.InsertOrUpdate);
            callback.Invoke(1, null);
        }

        protected override int ExecuteDelete(IDictionary keys, IDictionary oldValues)
        {
            this.SaveUpdate(keys, null, UpdateMode.Delete);
            return 1;
        }

        public IOrderedDictionary SelectKeys
        {
            get;
            set;
        }

        public string UpdateClassTypeName { get; set; }

        public string ListClassTypeName { get; set; }

        public bool SelectByRecord { get; set; }

        protected Type _updateClassType;

        protected Type UpdateClassType
        {
            get
            {
                if (_updateClassType == null)
                    _updateClassType = BuildManager.GetType(UpdateClassTypeName, /*throwOnFail*/true, /*ignoreCase*/true);
                return _updateClassType;
            }
        }

        protected Type _listClassType;

        protected Type ListClassType
        {
            get
            {
                if (_listClassType == null)
                    _listClassType = BuildManager.GetType(ListClassTypeName, /*throwOnFail*/true, /*ignoreCase*/true);
                return _listClassType;
            }
        }

        protected object GetInstance(Type classType, IDictionary keys)
        {

            object classinstance = Activator.CreateInstance(classType);
            //设置keys
            if (keys != null)
            {
                foreach (DictionaryEntry entry in keys)
                {
                    var pinfo = classType.GetProperty(entry.Key.ToString());
                    pinfo.SetValue(classinstance, entry.Value, null);
                }
            }
            return classinstance;
        }

        protected override System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
        {
            Type classType = this.SelectByRecord ? UpdateClassType : ListClassType;
            object classinstance = GetInstance(classType, this.SelectKeys);
            //处理GetRecord
            string mname = this.SelectByRecord ? "GetRecord" : "GetArray";
            MethodInfo method;
            if (this.SelectByRecord)
            {
                method = classType.GetMethod(mname, Type.EmptyTypes);
                return new object[] { method.Invoke(classinstance, null) };
            }
            else
            {
                method = classType.GetMethods().First(r => r.Name == mname && r.IsGenericMethod == false && r.GetParameters().Length == 0);

                return (method.Invoke(classinstance, null) as System.Collections.IEnumerable);
            }
        }
    }
}